import java.util.Calendar;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

/*
 * This class is responsible for handling the feed which provides the jobs to be scheduled. It
 * is responsible for creating the "jobs" and putting the jobs in a jobQueue. This jobQueue then
 * needs to be transferred to the job handler class. 
 * 
 * ==== This object would create job queue and then transfer it to the job handler object. It would do so by a method call to the job
 * ==== handler object, because both these objects are running as separate threads.
 * 
 * === Need to add the following methods for creating jobs in different ways:
 * 			1. A method which creates a single job as per the given characteristics
 * 			2. A method to create the specified no of jobs with random instances
 */

public class JobFeeder implements IJobFeeder, Runnable
{
	private Queue<IJob> myJobQueue = null;	// Queue for storing ALL JOBS
	private IJob currentJob = null;			// Variable for storing current job under execution	
	private int universalJobCount = 0;
	
	protected volatile Boolean running = null;
	protected IJobHandler jobHandler = null;
	
	public JobFeeder(Boolean running)
	{
		myJobQueue = new LinkedList<IJob>();
		
		this.running = running;
	}
	
	public void run()
	{
		// method called by controlling class to start reading the feed and creating jobs
		System.out.println("Job Feeder started !!");
		
		while(running)
		{
			//System.out.println("Creating and sending jobs ...");
			
			if(!myJobQueue.isEmpty())				
				this.sendJobFromQueue();
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				System.out.println("Exception in job feeder sleeping");
				e.printStackTrace();
			}
		}
		
		System.out.println("Job feeder finished !!");
	}
	
	private IJob createRandomJob() 
	{
		// method to create a random job.
		
		IJob tempJob = null;
		char jobPriority;
		
		Calendar timeObject = Calendar.getInstance();
		Random randomVariable = new Random();
		
		long resourceMemoryLevel = randomVariable.nextInt(1024000);		// In terms of KB = 1000 MB Random Generator
		int timeRequired = randomVariable.nextInt(500);
		int priorityNumber = randomVariable.nextInt();
		int processing_elements = randomVariable.nextInt(4);
		
		while(processing_elements <= 0)
			processing_elements = randomVariable.nextInt(4);	// No job with 0 npu's allowed !!
		
		while(timeRequired <= 0)
			timeRequired = randomVariable.nextInt(randomVariable.nextInt(500));		// No job with 0 duration allowed !!
		
		while(resourceMemoryLevel <= 0)			// No job with 0 memory allowed !!
			resourceMemoryLevel = randomVariable.nextInt(1024000);
		
		if(priorityNumber % 2 == 0)		// Most probable
			jobPriority = 'L';
		else if(priorityNumber % 3 == 0)	// Least probable
			jobPriority = 'H';
		else 							// Medium probability
			jobPriority = 'M';
		
		
		tempJob = new Job("Job" + String.valueOf(universalJobCount++),
							"Random Job Created @ " + timeObject.getTime().toString(),
							resourceMemoryLevel,timeRequired,
							jobPriority,processing_elements);
		
		return tempJob;
	}
	
	private void sendJobFromQueue()
	{
		// method to create a single job from the given job characteristics.
		
		currentJob = null;
		
		currentJob = myJobQueue.remove();
		
		assignJobToHandler();
	}
	
	private void assignJobToHandler()
	{
		// method call to pass the currently created job to the job handler.
		
		if((currentJob != null) && (jobHandler != null))
		{
			jobHandler.jobIn(currentJob);
			currentJob = null;
			
			System.out.println("Job assigned to handler");
		}
		
		else
			System.out.println("Error in creating job. A null job or job handler exists !!");
	}
	
	public void assignJobHandlerObject(IJobHandler jobHandler)
	{
		this.jobHandler = jobHandler;
	}
	
	public void setMultipleJobs(int n)
	{
		if(n > 0)
		{
			// create n jobs and put them in the jobQueue
			
			for(int i=0;i<n;i++)
			{
				myJobQueue.add(createRandomJob());
				
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		else
		{
			System.out.println("Error, illegal value entered for no of jobs to send !!");
		}
	}
	
	public void setSingleJob(String jName, String jDescription, int jDuration, long jMemoryLevel, char jPriority, int jHour, int jMinute, int jSecond,int npe)
	{
		if((!jName.equals("")) && (jDuration > 0) 
				&& (!jDescription.equals(""))
				&& (jMemoryLevel > 0)
				&& ((jPriority == 'L') || (jPriority == 'M') || (jPriority == 'H'))
				&& (npe >= 1))
		{
			IJob tempJob = new Job(jName,jDescription,jMemoryLevel,jDuration,jPriority,npe);
			
			if((jHour >= 0) && (jMinute >= 0) && (jSecond >= 0))
			{
				tempJob.setStartHour(jHour);
				tempJob.setStartMinute(jMinute);
				tempJob.setStartSecond(jSecond);
			}
			
			myJobQueue.add(tempJob);
			universalJobCount++;
		}
		
		else
		{
			System.out.println("Error, wrong values entered for a single job !!");
		}
	}
}
